package service

import (
	"fmt"
	"go-admin-auth/app/dal"
	"go-admin-auth/app/lib"
	"go-admin-auth/app/models"
	"go-admin-auth/httpapi/dto"
	"strconv"
	"strings"
)

type roleMenuPermSrv struct{}

var (
	RoleMenuPermSrv = &roleMenuPermSrv{}
)

func (srv *roleMenuPermSrv) Query(f *dto.RoleMenuPermQueryForm) ([]*dto.RoleMenuPermDTO, error) {
	form := new(dto.RoleQueryForm)
	form.PageForm = dto.PageForm{
		Page:  1,
		Psize: 10000,
	}
	roleList, err := dal.RoleDAO.GetList(form)
	if err != nil {
		return nil, err
	}

	result := make([]*dto.RoleMenuPermDTO, 0)
	for _, role := range roleList {
		res := new(dto.RoleMenuPermDTO)
		res.TRole = role
		res.MenuIdList = make([]int, 0)
		res.OperaIdList = make([]int, 0)
		res.MenuOperaCombine = make([]string, 0)

		form := new(dto.RoleMenuQueryForm)
		form.RoleId = role.Id
		roleMenuList, err := dal.RoleMenuDAO.GetList(form)
		if err != nil {
			return nil, err
		}

		for _, v := range roleMenuList {
			if !lib.IsInSliceInt(v.MenuId, res.MenuIdList) {
				res.MenuIdList = append(res.MenuIdList, v.MenuId)
			}

			operaStrList := strings.Split(v.OperaIds, ",")
			for _, operaIdStr := range operaStrList {
				operaIdInt, _ := strconv.Atoi(operaIdStr)
				if operaIdInt == 0 {
					continue
				}
				res.OperaIdList = append(res.OperaIdList, operaIdInt)
				res.MenuOperaCombine = append(res.MenuOperaCombine, fmt.Sprintf("%v_%v", v.MenuId, operaIdStr))
			}
		}

		result = append(result, res)
	}

	return result, nil
}

func (srv *roleMenuPermSrv) Get(roleId int, systemId int) (*dto.RoleMenuPermDTO, error) {
	role, err := dal.RoleDAO.Get(roleId)
	if err != nil {
		return nil, err
	}

	res := new(dto.RoleMenuPermDTO)
	res.TRole = role
	res.MenuIdList = make([]int, 0)
	res.OperaIdList = make([]int, 0)
	res.MenuOperaCombine = make([]string, 0)

	form := new(dto.RoleMenuQueryForm)
	form.SystemId = systemId
	form.RoleId = roleId
	roleMenuList, err := dal.RoleMenuDAO.GetList(form)
	if err != nil {
		return nil, err
	}

	for _, v := range roleMenuList {
		if !lib.IsInSliceInt(v.MenuId, res.MenuIdList) {
			res.MenuIdList = append(res.MenuIdList, v.MenuId)
		}

		operaStrList := strings.Split(v.OperaIds, ",")
		for _, operaIdStr := range operaStrList {
			operaIdInt, _ := strconv.Atoi(operaIdStr)
			if operaIdInt == 0 {
				continue
			}
			res.OperaIdList = append(res.OperaIdList, operaIdInt)
			res.MenuOperaCombine = append(res.MenuOperaCombine, fmt.Sprintf("%v_%v", v.MenuId, operaIdStr))
		}

	}

	return res, nil
}

func (srv *roleMenuPermSrv) Update(m *dto.RoleMenuPermForm) error {
	// 每个menu生成一条记录
	result := make([]*models.TRoleMenu, 0)

	// 处理 OperaList 挂到对应的 menu上
	menuOperation := make(map[int][]string, 0)
	for _, v := range m.OperaList {
		menuOper := strings.Split(v, "_")
		if len(menuOper) != 2 {
			continue
		}

		menuId, _ := strconv.Atoi(menuOper[0])

		menuOperation[menuId] = append(menuOperation[menuId], menuOper[1])
	}

	// 生成相关记录
	for _, v := range m.MenuIdList {
		row := new(models.TRoleMenu)
		row.SystemId = m.SystemId
		row.RoleId = m.RoleId
		row.MenuId = v
		row.OperaIds = strings.Join(menuOperation[v], ",")

		result = append(result, row)
	}

	// 删除已存在的所有
	_ = dal.RoleMenuDAO.RealDeleteByRoleId(m.RoleId)

	// 插入新记录
	err := dal.RoleMenuDAO.BatchInsert(result)
	return err
}
